/*
 * Lenovo Group
 * Copyright (c) 2015-2016 All Rights Reserved.
 * 
 * Project Name:assign-tracer
 * Create Time: 2016年2月14日 上午10:56:08
 */
package com.lenovo.lmrp.server.assigntracer.repository;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lenovo.lmrp.api.constant.TicketPolicy;
import com.lenovo.lmrp.api.constant.TicketStatus;
import com.lenovo.lmrp.api.model.entity.AssigningTicketPO;
import com.lenovo.lmrp.api.model.entity.TicketExtensePO;
import com.lenovo.lmrp.api.model.entity.TicketPO;
import com.lenovo.lmrp.api.model.entity.TicketSLAPO;
import com.lenovo.lmrp.api.model.view.SearchListFilter;
import com.lenovo.lmrp.api.model.view.TicketTotalVO;
import com.lenovo.lmrp.server.assigntracer.domain.service.TicketService;
import com.lenovo.lmrp.server.assigntracer.domain.ticket.ITicketRepository;
import com.lenovo.lmrp.server.assigntracer.domain.ticket.TicketBO;
import com.lenovo.sdc.framework.dao.ADaoFactory;
import com.lenovo.sdc.framework.dao.ICommonDAO;
import com.lenovo.sdc.framework.dao.ICommonDAO.FinderEnum;
import com.lenovo.sdc.framework.mq.AMQClient;
import com.lenovo.sdc.framework.dao.IQueryExecutor;
import com.lenovo.sdc.framework.util.AttributeBean;
import com.lenovo.sdc.framework.util.CommonUtil;
import com.lenovo.sdc.framework.util.PageData;
import com.lenovo.sdc.framework.util.exception.ErrorCode;
import com.lenovo.sdc.framework.util.exception.TraceableException;

/**
 * @author songyz
 *
 */
public class TicketRepository implements ITicketRepository {
    
    private static final Logger logger = LoggerFactory.getLogger(TicketRepository.class);
    
	private TicketService ticketService;
	private AMQClient mqclient;
	private AttributeBean attributes;

	@Inject
	public void set(AMQClient mqclient) {
		this.mqclient = mqclient;
	}

	@Inject
	public void set(TicketService ticketService) {
		this.ticketService = ticketService;
	}
	
	@Inject
	public void set(AttributeBean attributes) {
	    this.attributes = attributes;
	}

	@Override
	public TicketBO createTicketBO(String itsmCode, TicketPO ticketPO) {
		if (Objects.isNull(ticketPO))
			return null;
		else
			return new TicketBO(itsmCode, ticketPO, ticketService);
	}

	@Override
	public TicketBO createTicketBOwithMQClient(String itsmCode, TicketPO ticketPO, boolean withMQ) {
		if (Objects.isNull(ticketPO))
			return null;
		else {
			if (withMQ) {
				return new TicketBO(itsmCode, ticketPO, ticketService, mqclient);
			} else {
				return new TicketBO(itsmCode, ticketPO, ticketService);
			}
		}
	}

	@Override
	public TicketBO createTicketBO(String itsmCode, String ticketId, boolean withExt) {
		try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
			TicketPO po = dao.get(TicketPO.class, ticketId);
			if (Objects.isNull(po))
				return null;
			else {
				if (withExt)
					po.setOthers(dao.get(TicketExtensePO.class, ticketId));
				return new TicketBO(itsmCode, po, ticketService);
			}
		} catch (Exception e) {
			throw new TraceableException(ErrorCode.DB_QUERY_FAILED, e);
		}
	}

	@Override
	public void store(String itsmCode, TicketPO TicketPO) {
		try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
			dao.beginTrans();
			dao.save(TicketPO);
			dao.endTrans();
		} catch (Exception e) {
			throw new TraceableException(ErrorCode.DB_UPDATE_FAILED, e);
		}
	}

	@Override
	public void store(String itsmCode, AssigningTicketPO assigningTicketPO) {
		try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
			dao.beginTrans();
			dao.save(assigningTicketPO);
			dao.endTrans();
		} catch (Exception e) {
			throw new TraceableException(ErrorCode.DB_UPDATE_FAILED, e);
		}
	}

	/**
	 * 工单列表查询 根据status条件区分 接单列表、抢单列表、活动工单列表和历史工单列表
	 * 
	 * @param itsmcode
	 * @param filter
	 * @return
	 */
	public List<TicketPO> getTicketList(String itsmcode, SearchListFilter searchFilter) {
		List<TicketPO> tickets = new ArrayList<>();
		try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
		    //查询sql
		    StringBuilder select = new StringBuilder("select b.id,caption,b.projectid as projectId,b.customerid as customerId"
		                    + ",b.priority,b.severity,b.policy,b.createtime as createTime,b.starttime as startTime"
		                    + ",b.updatetime as updateTime,b.description,b.creater,b.assignee,b.status"
		                    + ",b.longitude,b.latitude");
		    StringBuilder sql = new StringBuilder(" from itsm_ticket b");
		    StringBuilder assignSql = new StringBuilder(" from itsm_assigning_ticket as a,itsm_ticket as b "
		                    + " where a.ticketid = b.id");
		    //查询条件
		    List<Object> params = new ArrayList<>();
		    if (Objects.nonNull(searchFilter.getStatus())) {
		        TicketStatus status = TicketStatus.get(searchFilter.getStatus());
		        if (Objects.nonNull(status)) {
		            if (status == TicketStatus.GRABBING || status == TicketStatus.ACCEPTING) {
		                int assignpolicy = status == TicketStatus.GRABBING ? TicketPolicy.GRAB.getPolicy() : TicketPolicy.ACCEPT.getPolicy();
		                assignSql.append(" and b.status = ?");
                        params.add(status.getStatus());
                        assignSql.append(" and a.engineerid = ?");
                        params.add(searchFilter.getEngineer());
                        assignSql.append(" and a.assignpolicy = ?");
                        params.add(assignpolicy);
		            }
		            else if(status == TicketStatus.INEXCUTION) {
		                sql.append(" where b.status in (?,?)");
                        params.add(TicketStatus.INEXCUTION.getStatus());
                        params.add(TicketStatus.FINISHED.getStatus());
                        sql.append(" and b.assignee = ?");
                        params.add(searchFilter.getEngineer());
		            }
		            else if(status == TicketStatus.CLOSED) {
                        sql.append(" where b.status in (?,?)");
                        params.add(TicketStatus.CLOSED.getStatus());
                        params.add(TicketStatus.BREAK.getStatus());
                        sql.append(" and b.assignee = ?");
                        params.add(searchFilter.getEngineer());
                    }
		            else {
		                sql.append(" where b.status = ?");
                        params.add(status.getStatus());
                        sql.append(" and b.assignee = ?");
                        params.add(searchFilter.getEngineer());
		            }
		            //判断是否抢单/派单列表
		            boolean isGrab = sql.indexOf("where") == -1;
		            //地图经纬度
		            if (Objects.nonNull(searchFilter.getRectangle()) && !searchFilter.getRectangle().isEmpty()) {
		                if (isGrab) {
		                    assignSql.append(" and b.longitude between ? and ?");
		                    assignSql.append(" and b.latitude between ? and ?");
		                }
		                else {
		                    sql.append(" and b.longitude between ? and ?");
		                    sql.append(" and b.latitude between ? and ?");
		                }
		                params.add(searchFilter.getBetweenLng()[0]);
                        params.add(searchFilter.getBetweenLng()[1]);
		                params.add(searchFilter.getBetweenlat()[0]);
                        params.add(searchFilter.getBetweenlat()[1]);
		            }
		            //项目
		            if (Objects.nonNull(searchFilter.getProject())) {
		                if (isGrab) {
		                    assignSql.append(" and b.projectId = ?");
		                }
		                else {
		                    sql.append(" and b.projectId = ?");
		                }
		                params.add(searchFilter.getProject());
		            }
		            if (isGrab) {
                        assignSql.append(" order by a.notifyTime desc");
		            }
		            else {
                        sql.append(" order by b.createtime desc");
		            }
		            PageData<TicketPO> pagedata = new PageData<>(searchFilter.getPage(), searchFilter.getLimit(), false);
		            dao.getRegisteredFinder(FinderEnum.SQL).findMappedRecord(isGrab ? select.append(assignSql).toString() : select.append(sql).toString(), TicketPO.class, params.toArray(), pagedata);
		            tickets = pagedata.getPageData();
		            // 查询工单附属信息
		            for (TicketPO tp : tickets) {
		                TicketExtensePO extense = dao.get(TicketExtensePO.class, tp.getId());
		                tp.setOthers(extense);
		            }
		        }
		    }
		} catch (Exception exp) {
		    TraceableException.writeLog(ErrorCode.DB_QUERY_FAILED, "get ticket list error", exp);
		}
        return tickets;
	}

	/**
	 * 查询工程师可见的派单和抢单的工单总数
	 * 
	 * @param itsmcode
	 * @param engineer
	 *            工程师登录帐号
	 * @return
	 */
	public TicketTotalVO getAssigningTicketsByEngineer(String itsmcode, String engineer) {		
		if (CommonUtil.isNullOrEmpty(engineer)) {
			return null;
		}
		try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
		    String sql = "select sum(case when assignPolicy = 0 then 1 else 0 end) as acceptqty," +
                          "sum(case when assignPolicy = 1 then 1 else 0 end) as grabqty" +
                          " from itsm_assigning_ticket" +
                          " where engineerId = ?";
		    TicketTotalVO total = dao.getRegisteredFinder(FinderEnum.SQL).getSingleRecord(sql, TicketTotalVO.class, new Object[]{engineer});
		    return total;
		} catch (Exception exp) {
			throw new TraceableException(ErrorCode.DB_QUERY_FAILED, exp);
		}
	}

	/**
	 * 查询工单详情
	 * 
	 * @param itsmcode
	 * @param ticketId
	 * @return
	 */
	public TicketPO getTicket(String itsmcode, String ticketId) {
		try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
			return dao.get(TicketPO.class, ticketId);
		} catch (Exception exp) {
			throw new TraceableException(ErrorCode.DB_QUERY_FAILED, exp);
		}
	}

	/**
	 * 查询工单SLA信息
	 * 
	 * @param itsmcode
	 * @param ticketId
	 * @return
	 */
	public TicketSLAPO getTicketCurrentSLA(String itsmcode, String ticketId) {
		try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
			String hql = "from TicketSLAPO a " + "where a.ticketId = ? and a.finished = 0 " + "order by a.step";
			IQueryExecutor executor = dao.getRegisteredFinder(FinderEnum.HQL);
			List<TicketSLAPO> slapos = executor.findMappedRecord(hql, TicketSLAPO.class, new String[] { ticketId });
			return slapos.size() > 0 ? slapos.get(0) : null;
		} catch (Exception exp) {
			throw new TraceableException(ErrorCode.DB_QUERY_FAILED, exp);
		}
	}
}
